package org.loveyoupeng.license.entities

import scala.collection.mutable.ListBuffer

trait Employee {
	this:User =>
	val departments = ListBuffer[Department]()

	val managers = ListBuffer[Employee]()
	
	val directReporters = ListBuffer[Employee]()

	def in(department:Department):Employee={
		departments += department 
		this
	}

	def roles():List[Role]={
		departments.flatten{dr=>dr.roles} toList
	}

	def rolesInDepartment(department:Department):List[Role]={
		departments.find{dw=>dw.name == department.name}.get.roles.toList
	}

	def is(role:Role):RoleCollector={
		new RoleCollector(this,role)
	}

	def manage(employee:Employee):Employee={
		employee.managers += this
		directReporters += employee
		this
	}
}

object Employee {
	def apply(name:String):User with Employee=new User(name) with Employee
}

class Department(val name:String) {
	val roles = ListBuffer[Role]()

    override def toString()=name

	private[entities] def +(role:Role):Department={
		roles += role
		this
	}

	private[entities] def ++(roles:TraversableOnce[Role]):Department={
		this.roles ++= roles
		this
	}
}

object Department {
	val COMPANY = Department("Company")
    def apply(name:String):Department = new Department(name)
}

class RoleCollector(val employee:Employee,role:Role){
	val roles = ListBuffer[Role]() += role

	def in(department:Department):Employee={
		department ++ roles
		employee in department
		employee
	}

	def and(role:Role):RoleCollector={
		roles += role
		this
	}
}

class Role(val name:String) {
    override def toString()=name

    override def equals(other:Any) = {
        other match {
            case that:Role => (this eq that) || (name == that.name)
            case _ => false
        }
    }

	def in(department:Department):Department={
		department + this
	}
}

object Role{
    val STAFF = Role("Staff")
    def apply(name:String):Role = new Role(name)
}

class Title(name:String) {
	override def toString()=name
}

object Title {
	def apply(name:String):Title=new Title(name)
}
